module reg_lr #(
    parameter DW  = 32,
    parameter RST = {DW{1'b0}}
) (
    input clk,
    input rst,
    input load,

    input  [DW-1:0] din,
    output [DW-1:0] dout
);

  logic [DW-1:0] data;

  always_ff @(posedge clk) begin
    if (rst) data <= RST;
    else if (load) data <= din;
  end

  assign dout = data;

endmodule

module reg_l #(
    parameter DW = 32
) (
    input clk,
    input load,

    input  [DW-1:0] din,
    output [DW-1:0] dout
);

  logic [DW-1:0] data;

  always_ff @(posedge clk) begin
    if (load) data <= din;
  end

  assign dout = data;

endmodule

module reg_r #(
    parameter DW  = 32,
    parameter RST = {DW{1'b0}}
) (
    input clk,
    input rst,

    input  [DW-1:0] din,
    output [DW-1:0] dout
);

  logic [DW-1:0] data;

  always_ff @(posedge clk) begin
    if (rst) data <= RST;
    else data <= din;
  end

  assign dout = data;

endmodule

module reg_next #(
    parameter DW = 32
) (
    input clk,

    input  [DW-1:0] din,
    output [DW-1:0] dout
);

  logic [DW-1:0] data;

  always_ff @(posedge clk) begin
    data <= din;
  end

  assign dout = data;

endmodule

module reg_latch #(
    parameter DW = 32
) (
    input clk,
    input rst,
    input [DW-1:0] din,
    input i_valid,
    output [DW-1:0] dout
);

  logic [DW-1:0] data;
  reg_l #(DW) data_r (
      .load(i_valid),
      .dout(data),
      .*
  );
  assign dout = i_valid ? din : data;
endmodule

